package com.npave.zryhadapter.job;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaSubscribeMessage;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.aliyun.dysmsapi20170525.models.SendSmsRequest;
import com.aliyun.dysmsapi20170525.models.SendSmsResponse;
import com.aliyun.tea.TeaException;
import com.aliyun.teautil.models.RuntimeOptions;
import com.npave.zryhadapter.config.AliyunSmsProperties;
import com.npave.zryhadapter.utils.JacksonUtil;
import com.npave.zryhadapter.utils.StringUtil;
import com.sun.org.apache.bcel.internal.generic.IF_ACMPEQ;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;

import com.aliyun.dysmsapi20170525.Client;

import javax.annotation.PostConstruct;

@Slf4j
@Component
@EnableScheduling
public class MessageJob {

    @Value("${serverInfo.url}")
    public String serverUrl;

    @Autowired
    private WxMaService wxMaService;

    @Autowired
    private AliyunSmsProperties properties;

    @Autowired
    private Client client;

    @Scheduled(initialDelay = 1, fixedDelay = 1, timeUnit = TimeUnit.MINUTES)
    public void run() {
        try {
            HttpResponse httpResponse = HttpRequest.get(serverUrl + "/api/message")
                    .timeout(5000)
                    .execute();
            if (httpResponse.isOk()) {
                JSONObject jsonBody = JSONUtil.parseObj(httpResponse.body());
                if (Objects.equals("0000", jsonBody.getStr("code"))) {
                    List<OrderMessage> list = JSONUtil.toList(jsonBody.getJSONArray("data"), OrderMessage.class);
                    String code = "1";
                    boolean status = false;
                    for (OrderMessage e : list) {
                        log.info(e.getMessage());
                        //  微信消息
                        if (Objects.equals(e.getMessageType(), 2)) {
                            status = sendWechatMessage(e.getAppId(), e.getOpenid(), e.getTmpId(), e.getPage(), e.getMessage());
                        } else {
                            List<String> list1 = JSONUtil.toList(e.getMessage(), String.class);
                            status = sendSmsMessage(e.getPhoneNo(),  e.getTmpId(), list1.toArray(new String[list1.size()]));
                        }
                        // 发送成功后
                        Map<String, String> resultObj = new HashMap<>();
                        resultObj.put("code", code);
                        // status 0等待发送 1已经发送 2发送失败
                        HttpUtil.createPost(serverUrl + StrUtil.format("/api/message/{}?status={}&content={}",
                                e.getId(), status ? 1 : 2, URLEncoder.encode(JSONUtil.toJsonStr(resultObj), "UTF-8")))
                                .timeout(3000)
                                .execute().body();
                    }
                }
            } else {
                log.error("查询失败:{}", httpResponse.body());
            }

        } catch (Exception e) {
            log.error("查询失败:", e);
        }
    }

    public boolean sendWechatMessage(String appId, String toUser, String templateId, String page, String content) {
        WxMaSubscribeMessage message = new WxMaSubscribeMessage();
        message.setToUser(toUser);
        message.setTemplateId(templateId);
        message.setPage(page);
        message.setData(JSONUtil.toList(content, WxMaSubscribeMessage.MsgData.class));

        try {
            wxMaService.switchoverTo(appId).getMsgService().sendSubscribeMsg(message);
        } catch (WxErrorException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    public boolean sendSmsMessage(String phone, String templateId, String[] params) {
        final String SUCCESS = "OK";
        try {
            // 请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID 和 ALIBABA_CLOUD_ACCESS_KEY_SECRET。
            // 工程代码泄露可能会导致 AccessKey 泄露，并威胁账号下所有资源的安全性。以下代码示例使用环境变量获取 AccessKey 的方式进行调用，仅供参考，建议使用更安全的 STS 方式，更多鉴权访问方式请参见：https://help.aliyun.com/document_detail/378657.html
            String templateParam = "{}";
            if (params.length == 1) {
                Map<String, String> data = new HashMap<>();
                data.put("code", params[0]);
                templateParam = JSONUtil.toJsonStr(data);
            } else if (params.length > 1) {
                Map<String, String> data = new HashMap<>();
                data.put("code", params[0]);
                for (int i = 1; i < params.length; i++) {
                    data.put("code" + i, params[i]);
                }
                templateParam = JSONUtil.toJsonStr(data);
            }
            log.info("发送短信:{}",templateParam);
            SendSmsRequest sendSmsRequest = new SendSmsRequest()
                    .setPhoneNumbers(phone)
                    .setSignName(properties.getSign())
                    .setTemplateCode(templateId)
                    .setTemplateParam(templateParam);
            // 复制代码运行请自行打印 API 的返回值
            SendSmsResponse sendSmsResponse = client.sendSmsWithOptions(sendSmsRequest, new RuntimeOptions());
            if (Objects.equals(sendSmsResponse.getBody().getCode(), SUCCESS)) {
                return true;
            } else {
                log.info("发送短信失败:【{}】", JSONUtil.toJsonStr(sendSmsResponse));
            }
        } catch (TeaException e) {
            // 如有需要，请打印 error
            log.info("发送短信失败:", e);
        } catch (Exception e) {
            log.info("发送短信失败:", e);
        }
        return false;
    }

    @Data
    public static class OrderMessage {
        private Integer id;

        private Integer messageType;

        private String title;

        private String lendSn;

        private String appId;

        private String tmpId;

        private String message;

        private String phoneNo;

        private String openid;

        private String page;

        private Integer receiverType;

        private String receiverCode;

        private String receiverName;

        private Integer messageStatus;

        private LocalDateTime createTime;

        private LocalDateTime updateTime;
    }
}

